Uptime Kuma 服務監控、跨節點守護、即時告警與狀態頁美化
1. 架構設計與多主機安全拓撲
在單一主機上,可以直接掛載 /var/run/docker.sock;若容器分散在多台實體機或 VPS,直接把未加密的 Docker Socket 暴露到外網等同開放 Root 提權。
因此,多主機監控架構的標準安全解法是引入 docker-socket-proxy:
[Uptime Kuma 中心伺服器]
│
├─► 監控本機容器: 掛載本地 /var/run/docker.sock:ro
│
├─► 監控遠端主機 A: 透過 TCP 2375 查詢 (受 docker-socket-proxy 唯讀保護)
│ ▲
│ └─ [遠端節點 A] ── docker-socket-proxy ── /var/run/docker.sock
│
├─► 異常觸發時 ───► Telegram Bot API ───► 即時推播至手機 / 群組
│
└─► 外部訪客 ───► 專屬狀態頁 (Status Page) ───► 毛玻璃深色主題展示
docker-socket-proxy的防護機制:底層透過 HAProxy 攔截 Docker API 請求。透過設定POST=0關閉所有寫入、建立與刪除權限,僅開放CONTAINERS=1等唯讀端點,杜絕攻擊者藉由暴露的 Docker 埠提權控制宿主機。
2. Docker Compose 部署配置
2.1 遠端受控節點:部署 docker-socket-proxy(多主機適用)
在遠端 VPS 或受控節點上建立 /opt/dockerproxy/docker-compose.yml:
services:
dockerproxy:
image: ghcr.io/tecnativa/docker-socket-proxy:latest
container_name: dockerproxy
restart: unless-stopped
environment:
# 僅開放監控所需的唯讀權限
- CONTAINERS=1
- SERVICES=1
- TASKS=1
- POST=0
- BUILD=0
- COMMIT=0
- CONFIGS=0
- DISTRIBUTION=0
- EXEC=0
- IMAGES=0
- INFO=0
- NETWORKS=0
- NODES=0
- PLUGINS=0
- SECRETS=0
- SESSION=0
- SWARM=0
- SYSTEM=0
- VOLUMES=0
ports:
# 建議僅在內網或 WireGuard VPN 網段開放;若走公網務必以防火牆限制來源 IP
- "2375:2375"
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
2.2 中心伺服器:部署 Uptime Kuma 本體
建立 /opt/uptime-kuma/docker-compose.yml:
services:
uptime-kuma:
image: louislam/uptime-kuma:1
container_name: uptime-kuma
restart: unless-stopped
ports:
# 直連預設 Port,若前方有 NPM / Traefik 可取消對外映射
- "3001:3001"
volumes:
- /opt/uptime-kuma/data:/app/data
# 掛載本機 socket 監控本地容器
- /var/run/docker.sock:/var/run/docker.sock:ro
networks:
- monitor-net
# 若需走反向代理,加入 proxy 網路
- proxy-network
networks:
monitor-net:
driver: bridge
proxy-network:
external: true
啟動服務:
docker compose up -d
3. Telegram 告警機器人完整串接步驟
步驟 A:向 BotFather 申請 Bot Token
-
在 Telegram 搜尋官方機器人
@BotFather。 -
發送指令
/newbot。 -
依序輸入機器人顯示名稱(Name)與使用者名稱(Username,結尾必須為
bot,例如HomeLab_alert_bot)。 -
儲存回傳的 HTTP API Token(格式如:
123456789:ABCdefGhIJKlmNoPQRsTUVwxyZ)。
步驟 B:取得個人或群組 chat_id
-
在 Telegram 搜尋剛剛建立的機器人,點擊 Start 或傳送任意訊息給它。
-
取得 Chat ID:
-
方法 1:在瀏覽器訪問
[https://api.telegram.org/bot](https://api.telegram.org/bot)<YOUR_BOT_TOKEN>/getUpdates,在返回的 JSON 內找到"chat":{"id": 123456789, ...}。 -
方法 2:在 Telegram 搜尋
@userinfobot並點擊 Start,它會直接返回你的個人數字Id。
-
步驟 C:於 Uptime Kuma 綁定通知管道
-
開啟 Uptime Kuma 後台 (
http://<IP>:3001) -> 點擊右上角頭像 -> 設定 (Settings) -> 通知 (Notification) -> 設定通知 (Setup Notification)。 -
類型選擇 Telegram:
-
Bot Token:貼上剛取得的 API Token。
-
Chat ID:填入數字 ID。
-
-
點選 測試 (Test),確認 Telegram 收到測試訊息後存檔。
4. 監控項目建立 (Docker 容器監控)
點擊左上角「新增監控項目」:
-
監控本地容器:
-
監控類型:選擇
Docker 容器 (Docker Container)。 -
Docker 節點 (Docker Host):選擇預設的
/var/run/docker.sock。 -
容器名稱/ID:輸入目標容器名稱(如
nextcloud、gitea)。
-
-
監控遠端節點容器 (經由 Socket Proxy):
-
至 設定 -> Docker 主機 -> 新增 Docker 主機。
-
連線方式選
TCP Socket,位址填入tcp://<REMOTE_VPS_IP>:2375。 -
新增監控項目時,下拉選單切換至該遠端主機,即可填寫該主機上的容器名稱進行跨機監控。
-
5. 進階維運玩法
5.1 「死人開關 (Dead Man's Switch)」:Push 被動心跳監控
一般監控是主動 Ping 目標,但若要確認備份腳本、NAS 任務或 Cron Job 有沒有準時跑完,應使用 Push 模式:
-
監控類型選擇 「Push」,設定心跳間隔(例如 86400 秒 = 1 天)。
-
Kuma 會生成一組專屬 Webhook URL:
[https://kuma.example.com/api/push/keyXYZ?status=up&msg=OK&ping=](https://kuma.example.com/api/push/keyXYZ?status=up&msg=OK&ping=) -
在備份腳本末端加入打卡指令:
curl -fsS -m 10 --retry 3 "https://kuma.example.com/api/push/keyXYZ?status=up&msg=BackupSuccess"
- 若腳本異常崩潰或卡死,Kuma 在時間內未收到回報便會立刻觸發警報。
5.2 搭配 Webhook 實現「服務崩潰自動重啟 (Self-Healing)」
當容器異常中斷時,除傳送訊息外,可驅動外部服務自動救回:
-
在通知設定中新增 Webhook。
-
串接 Node-RED 或輕量級 Webhook 伺服器(如
adnanh/webhook)。 -
當收到事件
DOWN時,由背景服務自動執行docker restart <container_name>,達成故障自癒。
5.3 內建 SSL 憑證即期自動告警
監控類型選擇 HTTP(s) 並填入域名,Kuma 會自動提取 TLS 憑證鏈,預設在憑證到期前 21、14、7 天 主動推播,避免 Let's Encrypt 自動續期失效引發中斷。
6. 公開狀態頁 (Status Page) 與 Custom CSS 毛玻璃美化
Uptime Kuma 支援建立獨立的展示頁面供訪客 確認各項服務可用度。
6.1 建立狀態頁面
-
點選頂部選單的 狀態頁面 (Status Pages) -> 新增狀態頁面。
-
設定頁面名稱、Slug(如
/status)與分組項目。 -
點選右上角 編輯 (Edit),展開底部的 自訂 CSS (Custom CSS) 區塊。
6.2 完整毛玻璃暗黑主題 CSS
將以下代碼完整貼入 Custom CSS 欄位並儲存:
/* ============================================================
Uptime Kuma Status Page - Modern Glassmorphism Theme
============================================================ */
/* 1. 全域深色漸層背景 */
body {
background-color: #0d1117 !important;
background-image:
radial-gradient(at 0% 0%, rgba(56, 189, 248, 0.12) 0px, transparent 50%),
radial-gradient(at 100% 100%, rgba(139, 92, 246, 0.12) 0px, transparent 50%),
radial-gradient(at 50% 50%, rgba(15, 23, 42, 0.8) 0px, transparent 100%) !important;
background-attachment: fixed !important;
color: #e2e8f0 !important;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif !important;
}
/* 2. 頁首與整體狀態大看板毛玻璃化 */
header, .overall-status {
backdrop-filter: blur(16px) !important;
-webkit-backdrop-filter: blur(16px) !important;
}
.overall-status {
background: rgba(30, 41, 59, 0.45) !important;
border: 1px solid rgba(255, 255, 255, 0.08) !important;
border-radius: 16px !important;
box-shadow: 0 8px 32px 0 rgba(0, 0, 0, 0.3) !important;
padding: 24px !important;
}
/* 3. 監控群組容器與服務卡片 (Card) */
.item-list, .shadow-box {
background: rgba(30, 41, 59, 0.4) !important;
backdrop-filter: blur(12px) !important;
-webkit-backdrop-filter: blur(12px) !important;
border: 1px solid rgba(255, 255, 255, 0.08) !important;
border-radius: 14px !important;
box-shadow: 0 4px 24px -1px rgba(0, 0, 0, 0.25) !important;
transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1) !important;
}
/* 4. 單一服務條目懸停反饋 */
.item {
border-radius: 10px !important;
padding: 10px 14px !important;
transition: all 0.2s ease-in-out !important;
}
.item:hover {
background: rgba(255, 255, 255, 0.04) !important;
transform: translateY(-2px);
}
/* 5. 狀態心跳長條條 (Heartbeat Bar) 與發光霓虹樣式 */
.beat {
border-radius: 4px !important;
margin: 0 1.5px !important;
transition: transform 0.15s ease !important;
}
.beat:hover {
transform: scaleY(1.3);
}
/* 在線 (UP) 綠色發光 */
.bg-primary, .badge.bg-primary {
background-color: #10b981 !important;
box-shadow: 0 0 12px rgba(16, 185, 129, 0.35) !important;
}
/* 離線 (DOWN) 紅色呼吸警示發光 */
.bg-danger, .badge.bg-danger {
background-color: #ef4444 !important;
box-shadow: 0 0 14px rgba(239, 68, 68, 0.5) !important;
}
/* 維護中 (Maintenance) 藍色 */
.bg-info, .badge.bg-info {
background-color: #0ea5e9 !important;
box-shadow: 0 0 10px rgba(14, 165, 233, 0.35) !important;
}
/* 6. 群組標題 (Group Title) */
.group-title {
color: #94a3b8 !important;
font-weight: 600 !important;
letter-spacing: 0.05em !important;
text-transform: uppercase !important;
font-size: 0.85rem !important;
margin-bottom: 12px !important;
border-bottom: 1px solid rgba(255, 255, 255, 0.06);
padding-bottom: 6px;
}
/* 7. 事件時間軸與維護公告 (Incidents) */
.incident {
background: rgba(30, 41, 59, 0.55) !important;
border-left: 4px solid #38bdf8 !important;
border-radius: 8px !important;
backdrop-filter: blur(8px) !important;
}
/* 8. 頁尾樣式微調 */
footer {
opacity: 0.65;
font-size: 0.85rem;
transition: opacity 0.2s;
}
footer:hover {
opacity: 1;
}
7. 備份與還原
Uptime Kuma 所有監控項目、自訂告警規則與歷史統計數據均存放在 /app/data/kuma.db(SQLite):
# 1. 備份資料目錄
sudo tar -czvf /opt/backups/uptime-kuma-$(date +%F).tar.gz -C /opt/uptime-kuma data
# 2. 恢復備份至新環境
sudo tar -xzvf /opt/backups/uptime-kuma-*.tar.gz -C /opt/uptime-kuma/
docker compose restart uptime-kuma